package com.sqlcheck.service.impl;

import com.sqlcheck.model.SqlStatement;
import com.sqlcheck.service.SqlBatchSplitter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * SQL分批拆分服务实现
 * 职责：仅负责根据字符长度将SQL语句分批
 * 
 * @author Claude
 * @version v4.2
 * @since 2025-09-04
 */
@Service
@Slf4j
public class SqlBatchSplitterImpl implements SqlBatchSplitter {

    // Token估算常量
    private static final double CHINESE_CHARS_PER_TOKEN = 2.0;
    private static final double ENGLISH_CHARS_PER_TOKEN = 0.75;

    @Value("${ai.verification.batching.max-sql-per-batch:5}")
    private int maxSqlPerBatch;

    @Override
    public List<SqlBatch> splitIntoBatches(List<SqlStatement> sqlStatements, int maxTokensPerBatch, int basePromptTokens) {
        log.info("开始分批处理SQL - 总语句数: {}, 每批最大SQL数: {}", 
                sqlStatements.size(), maxSqlPerBatch);

        List<SqlBatch> batches = new ArrayList<>();
        
        if (sqlStatements.isEmpty()) {
            log.warn("SQL语句列表为空，无法进行分批");
            return batches;
        }

        log.info("使用SQL数量分批模式 - 每批最多{}个SQL语句", maxSqlPerBatch);

        List<SqlStatement> currentBatch = new ArrayList<>();
        int batchNumber = 1;

        for (int i = 0; i < sqlStatements.size(); i++) {
            SqlStatement statement = sqlStatements.get(i);

            log.debug("处理语句 {}/{} (ID:{}, Number:{})", 
                    i + 1, sqlStatements.size(), statement.getId(), statement.getStatementNumber());

            // 检查是否需要开始新批次（基于SQL数量）
            if (currentBatch.size() >= maxSqlPerBatch) {
                // 创建当前批次
                int estimatedTokens = estimateBatchTokens(currentBatch, basePromptTokens);
                SqlBatch batch = new SqlBatch(batchNumber, new ArrayList<>(currentBatch), estimatedTokens);
                batches.add(batch);

                log.debug("创建批次 {} - 包含 {} 个语句, 预估 {} tokens", 
                        batchNumber, currentBatch.size(), estimatedTokens);

                // 开始新批次
                currentBatch.clear();
                batchNumber++;
            }

            // 添加语句到当前批次
            currentBatch.add(statement);
        }

        // 处理最后一个批次
        if (!currentBatch.isEmpty()) {
            int estimatedTokens = estimateBatchTokens(currentBatch, basePromptTokens);
            SqlBatch batch = new SqlBatch(batchNumber, new ArrayList<>(currentBatch), estimatedTokens);
            batches.add(batch);

            log.debug("创建最终批次 {} - 包含 {} 个语句, 预估 {} tokens", 
                    batchNumber, currentBatch.size(), estimatedTokens);
        }

        log.info("SQL分批完成 - 总共创建 {} 个批次，平均每批次 {} 个语句", 
                batches.size(), batches.isEmpty() ? 0.0 : (double) sqlStatements.size() / batches.size());
        
        return batches;
    }

    /**
     * 估算批次的总token数量
     */
    private int estimateBatchTokens(List<SqlStatement> statements, int basePromptTokens) {
        int totalTokens = basePromptTokens;
        for (int i = 0; i < statements.size(); i++) {
            totalTokens += estimateStatementTokens(statements.get(i), i + 1);
        }
        return totalTokens;
    }

    @Override
    public int estimateTokenCount(String text) {
        if (text == null || text.isEmpty()) {
            return 0;
        }

        int chineseChars = 0;
        int englishChars = 0;

        for (char ch : text.toCharArray()) {
            if (ch >= 0x4e00 && ch <= 0x9fff) { // 中文字符范围
                chineseChars++;
            } else if (Character.isLetterOrDigit(ch) || Character.isWhitespace(ch)) {
                englishChars++;
            }
        }

        int estimatedTokens = (int) Math.ceil(chineseChars / CHINESE_CHARS_PER_TOKEN + 
                englishChars / ENGLISH_CHARS_PER_TOKEN);

        return Math.max(1, estimatedTokens);
    }

    @Override
    public int estimateStatementTokens(SqlStatement statement, int statementIndex) {
        // 格式化后的语句在PROMPT中的大概格式
        String formattedStatement = String.format("### SQL语句 #%d\n**SQL内容**:\n```sql\n%s\n```\n\n", 
                statementIndex, statement.getContent());
        
        return estimateTokenCount(formattedStatement);
    }

    @Override
    public boolean shouldUseBatchProcessing(List<SqlStatement> sqlStatements, int maxTokensPerBatch, int basePromptTokens) {
        if (sqlStatements == null || sqlStatements.isEmpty()) {
            return false;
        }

        // 严格按照max-sql-per-batch和max-issues-per-task控制
        // 只要有SQL语句就进行分批处理（分批大小由max-sql-per-batch控制）
        log.debug("SQL语句数量: {}, 将按max-sql-per-batch({})进行分批处理", 
                sqlStatements.size(), maxSqlPerBatch);
        
        return true;
    }
}